package il.ac.tau.arielgue.outxing;

import il.ac.tau.arielgue.outxing.contexts.DemeSubContext;
import il.ac.tau.arielgue.outxing.contexts.OutXingContext;
import il.ac.tau.arielgue.outxing.contexts.PoolSubContext;
import il.ac.tau.arielgue.outxing.helpers.IdealOutXingParentFactory;
import il.ac.tau.arielgue.outxing.utils.Params;
import proevolution.FileDeserializationBuilder;
import proevolution.GenePoolImpl;
import proevolution.agents.Organism;
import proevolution.helpers.OrganismFactory;
import repast.simphony.dataLoader.ContextBuilder;
import repast.simphony.engine.environment.RunEnvironment;
import repast.simphony.context.Context;
import simphony.util.messages.MessageCenter;

public class OutXingContextBuilder implements ContextBuilder<Organism> {
	private static final MessageCenter logger = MessageCenter
			.getMessageCenter(OutXingContextBuilder.class);

	public Context<Organism> build(Context<Organism> context) {

		if (!Params.getInputFile().equals("-")) {
			// deserialize an OLD context
			ContextBuilder<Organism> builder = new FileDeserializationBuilder<Organism>(
					Params.getFreezedryFolder() + Params.getInputFile());
			context = (Context<Organism>) builder.build(context);
		} else {
			// create a NEW context
			OutXingContext mycontext = new OutXingContext(context.getId(),
					context.getTypeID());

			// create the aggregation pool
			PoolSubContext pool = new PoolSubContext("pool");
			pool.setMasterContext(mycontext);
			pool.setMaxPopulationSize(Params.getDemeCarryingCapacity()*Params.getNumberOfDemes()*1000);//TODO- formulate
			mycontext.setPool(pool);

			// create the DEMEs
			for (int i = 0; i < Params.getNumberOfDemes(); i++) {
				DemeSubContext deme = new DemeSubContext("deme" + i);
				deme.setMasterContext(mycontext);
				// TODO all demes have the same carrying capacity
				deme.setMaxPopulationSize(Params.getDemeCarryingCapacity());
				mycontext.addDeme(deme);
			}

			// create the GENE POOL
			GenePoolImpl genePool = createGenePool(Params.getNumberOfGenes(),
					Params.getNumberOfAlleles());
			genePool.setStandardSelectionModifier(Params
					.getStandardSelectionModifier());

			// create the GENES
			for (int gene = 0; gene < genePool.getNumOfGenes(); gene++) {
				genePool.setHousekeepingGene(gene);
			}
			mycontext.setGenePool(genePool);

			// create the POPULATION using a factory
			OrganismFactory organismFactory = new IdealOutXingParentFactory(
					mycontext);
			for (int i = 0; i < Params.getMaxPopulationSize(); i++) {
				mycontext.addToRandomDeme(organismFactory.create());
			}

			// set the return value to mycontext
			context = mycontext;
		}

		/* If running in batch mode, tell the scheduler when to end each run. */
		if (RunEnvironment.getInstance().isBatch()) {
			RunEnvironment.getInstance().endAt(Params.getRunLength());
		}
		return context;
	}

	protected GenePoolImpl createGenePool(int numberOfGenes, int numberOfAlleles) {
		return new GenePoolImpl(numberOfGenes, numberOfAlleles);
	}
}
